package org.elzat.healthboxgatewayapp.controller;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elzat.healthboxgatewayapp.util.ResultEntity;
import org.elzat.healthboxgatewayapp.credentials.HealthBoxUserRole;
import org.elzat.healthboxgatewayapp.dto.HealthBoxUserVO;
import org.elzat.healthboxgatewayapp.service.HealthBoxUserModifyService;
import org.elzat.healthboxgatewayapp.service.MessageTokenService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

import static org.elzat.healthboxgatewayapp.credentials.HealthBoxUserRole.SYSTEM_ADMIN;
import static org.elzat.healthboxgatewayapp.credentials.HealthBoxUserRole.USER;

@RestController
@AllArgsConstructor
@RequestMapping(value = "health-box-api/v1/register",
        produces = "application/json; charset=utf-8")
@Slf4j
public class UserRegisterController {

    private final HealthBoxUserModifyService modifyService;
    private final MessageTokenService tokenService;

    /**
     * 普通用户注册接口, 只能注册为USER角色的用户
     * 接口包含以下五个参数:
     *      1. userPhone    用户手机号
     *      2. idNumber     用户身份证号
     *      3. name         用户名
     *      4. password     用户密码
     *      5. token        短信验证码
     * 五个参数都是必要参数, 缺一不可
     *
     * 请求方式:
     *      POST .../register?userPhone=[]&idNumber=[]&name=[]&password=[]&token=[]
     *
     * 返回结果为data为ResultEntity类对象:
     *      {
     *          code: [成功返回200, 失败返回400]
     *          msg: [返回对应反馈消息]
     *          data: 失败时为null, 成功时
     *              {
     *                  "userPhone": [用户手机号],
     *                  "name": [用户名],
     *                  "idNumber": [用户身份证号],
     *                  "role": [用户角色]
     *              }
     *      }
     * */
    @PostMapping
    public ResultEntity<HealthBoxUserRegisterVO> register(
            @RequestParam String userPhone,
            @RequestParam String idNumber,
            @RequestParam String name,
            @RequestParam String password,
            @RequestParam String token
    ) {
        log.info("got request to register new user");
        ResultEntity<HealthBoxUserRegisterVO> result = register(userPhone, idNumber, name,
                password, token, USER, modifyService, tokenService);
        log.info("got registration result: " + result);
        return result;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    static class HealthBoxUserRegisterVO {
        public String userPhone;
        public String name;
        public String idNumber;
        public HealthBoxUserRole role;
        public static HealthBoxUserRegisterVO fromVO(HealthBoxUserVO vo) {
            return builder()
                    .userPhone(vo.userPhone)
                    .idNumber(vo.idNumber)
                    .name(vo.name)
                    .role(vo.role)
                    .build();
        }
    }

    static ResultEntity<HealthBoxUserRegisterVO> register(
            String userPhone, String idNumber, String name, String password,
            String token, HealthBoxUserRole role,
            HealthBoxUserModifyService modifyService, MessageTokenService tokenService
    ) {
        log.info("registering new user with info: userPhone=" + userPhone + "&idNumber"
                + idNumber + "&name=" + name + "&password" + password + "&token" + token
                + "&role=");
        Boolean duplicate = modifyService.hasDuplicateUserPhone(userPhone);
        if (duplicate) {
            log.info("discovered duplicate user phone in database: userPhone=" + userPhone);
            return ResultEntity
                    .failure()
                    .msg("手机号已存在")
                    .build();
        }
        duplicate = modifyService.hasDuplicateIdNumber(idNumber);
        if (duplicate) {
            log.info("discovered duplicate id number in database: idNumber=" + idNumber);
            return ResultEntity
                    .failure()
                    .msg("身份证号已存在")
                    .build();
        }
        Optional<String> maybe = tokenService.getTokenByPhoneNumber(userPhone);
        if (!maybe.isPresent() || !maybe.get().equals(token)) {
            log.info("invalid message token: " + token);
            return ResultEntity
                    .failure()
                    .msg("短信验证码无效")
                    .build();
        }
        HealthBoxUserVO vo = HealthBoxUserVO.builder()
                .id(null).idNumber(idNumber).userPhone(userPhone)
                .name(name).role(role).build();
        vo = modifyService.register(vo, password);
        log.info("got register info: " + vo);
        return vo == null ?
                ResultEntity.failure().msg("注册失败").build()
                : ResultEntity.ok().msg("注册成功").data(HealthBoxUserRegisterVO.fromVO(vo));
    }
}
